import React, { useCallback, useEffect, useRef, useState } from "react";
import Back from "@shared/back";
import GeekIcon from "@shared/geekIcon";
import { Skeleton } from "antd-mobile";
import styles from "@styles/article.module.less";
import { useParams } from "react-router-dom";
import { useRequestArticleQuery } from "@service/article";
import dayjs from "dayjs";
import localizedFormat from "dayjs/plugin/localizedFormat";
import "highlight.js/styles/atom-one-dark.css";
import Follow from "@pages/article/widgets/follow";
import Collect from "@pages/article/widgets/collect";
import Like from "@pages/article/widgets/like";
import Comment from "@pages/article/widgets/comment";
import Infinite from "@shared/infinite";
import { useLazyRequestCommentsQuery } from "@service/comments";
import { useTypedDispatch, useTypedSelector } from "@store/index";
import {
  clearComments,
  commentsSelectors,
  saveComments,
} from "@slice/comments";
import PublishComment from "@pages/article/widgets/publishComment";

dayjs.extend(localizedFormat);

export default function Article() {
  // 通过路由参数获取文章id
  const { id } = useParams();
  // 根据文章id获取文章详情
  const { data, isLoading } = useRequestArticleQuery(id!);
  // 用于存储文章标题、文章元信息、文章作者三块区域的父级
  const topRef = useRef<HTMLDivElement | null>(null);
  // 用于存储滚动区域的那个元素
  const articleRef = useRef<HTMLDivElement | null>(null);
  // 用于存储评论区域的元素对象
  const commentRef = useRef<HTMLDivElement | null>(null);
  // 是否渲染元素的标识
  const [isRender, setIsRender] = useState(false);
  // 标识页面位置 false 文章顶部 true 评论区域
  const [flag, setFlag] = useState(false);

  /*-------------------------*/
  // 数量偏移量
  const [offset, setOffset] = useState<string | undefined>();
  // 是否还有更多数据可以加载
  const [hasMore, setHasMore] = useState(true);
  // 用于获取评论列表的方法
  const [requestComments, { data: commentsResponse }] =
    useLazyRequestCommentsQuery();
  // 获取本地存储的评论列表
  const comments = useTypedSelector(commentsSelectors.selectAll);
  const dispatch = useTypedDispatch();

  // 用于加载更多数据
  const loadMore = () => {
    return requestComments({ type: "a", source: id!, offset, limit: 10 })
      .unwrap()
      .then(function (response) {
        // 保存评论列表
        dispatch(saveComments(response.data.results));
        // 设置获取数据的偏移量
        setOffset(response.data.last_id);
        // 设置是否还有更多数据可以加载
        setHasMore(response.data.last_id !== response.data.end_id);
      });
  };

  /*-------------------------*/

  // 监听滚动标识是否发生变化
  useEffect(() => {
    // 调节滚动位置
    articleRef.current?.scrollTo({
      top: flag ? commentRef.current?.offsetTop : 0,
      behavior: "smooth",
    });
  }, [flag]);

  // 离开文章详情页面的时候清空一下评论
  useEffect(() => {
    return () => {
      dispatch(clearComments());
    };
  }, [dispatch]);

  // 重置评论列表
  const resetComments = useCallback(() => {
    setOffset(undefined);
    setHasMore(true);
    dispatch(clearComments());
  }, [dispatch]);

  return (
    <>
      <div className={styles.header}>
        <div className={styles.left}>
          <Back />
          {isRender && (
            <div className={styles.center}>
              <img src={data?.data.aut_photo} alt="" />
              <span>{data?.data.aut_name}</span>
              <button>关注</button>
            </div>
          )}
        </div>
        <GeekIcon type={"icongengduo"} className={styles.more} />
      </div>
      <div
        className={styles.article}
        onScroll={(event) => {
          setIsRender(
            event.currentTarget.scrollTop > (topRef.current?.offsetHeight || 0)
          );
        }}
        ref={articleRef}
      >
        {isLoading && (
          <div className={styles.skeleton}>
            <Skeleton.Paragraph lineCount={2} animated />
            <Skeleton.Paragraph lineCount={3} animated />
            <Skeleton.Paragraph lineCount={5} animated />
            <Skeleton.Paragraph lineCount={2} animated />
            <Skeleton.Paragraph lineCount={4} animated />
          </div>
        )}
        <div ref={topRef}>
          <h2 className={styles.title}>{data?.data.title}</h2>
          <div className={styles.meta}>
            <span>
              {dayjs(data?.data.pubdate).locale("zh-cn").format("LL")}
            </span>
            <span>{data?.data.read_count} 阅读</span>
            <span>{data?.data.comm_count} 评论</span>
          </div>
          <div className={styles.author}>
            <div className={styles.avatar}>
              <img src={data?.data.aut_photo} alt="" />
              <span>{data?.data.aut_name}</span>
            </div>
            <Follow id={data?.data.aut_id} isFollow={data?.data.is_followed} />
          </div>
        </div>
        <div className={styles.content}>
          <div
            dangerouslySetInnerHTML={{ __html: data?.data.content || "" }}
          ></div>
          <div className={styles.footnote}>
            文章发布于：{dayjs(data?.data.pubdate).locale("zh-cn").format("LL")}
          </div>
        </div>
        <div className={styles.comment} ref={commentRef}>
          <h4 className={styles.title}>
            全部评论 ({commentsResponse?.data.total_count})
          </h4>
          {commentsResponse?.data.results.length === 0 && (
            <div className={styles.noReply}>
              <img src={require("@images/none.png")} alt="" />
              <span>还没有人评论哦</span>
            </div>
          )}
          {comments.map((comment) => (
            <Comment key={comment.com_id} comment={comment} />
          ))}
          <Infinite hasMore={hasMore} loadMore={loadMore} />
        </div>
      </div>
      <div className={styles.bar}>
        <PublishComment id={id!} resetComments={resetComments} />
        <div className={styles.icons}>
          <div className={styles.item} onClick={() => setFlag(!flag)}>
            <GeekIcon type={"iconbtn_comment"} />
            <span>评论</span>
          </div>
          <Like id={data?.data.art_id} isLike={data?.data.attitude} />
          <Collect id={data?.data.art_id} isCollect={data?.data.is_collected} />
          <div className={styles.item}>
            <GeekIcon type={"iconbtn_share"} />
            <span>分享</span>
          </div>
        </div>
      </div>
    </>
  );
}
